#pragma once

// CTasksThread
// 构建一个内部包含任务列表的、可向它派发异步任务的线程。

#include <functional>
#include <deque>
#include <mutex>
#include "pevents.h"
#include "threads.h"

namespace qcutil {
/**
 * @brief The CTasksThread class
 * 自带任务队列的线程对象，可以同步执行任务（任务在线程中执行后才返回）也可以异步发送任务（将任务添加到队列后返回）。
 * 执行start后将等待使用者传递任务给它，内部线程将逐个执行队列中的任务，直到stop被调用。
 */
class CTasksThread : public NonCopyable
{
public:
    CTasksThread();
    ~CTasksThread();
    typedef std::function<void()> callback_t;
public:
    /**
     * @brief start 开始任务线程，当工作线程启动时候将调用started_cb，退出前将调用terminated_cb。
     * @param started_cb 这个传入的函数对象将在工作线程启动时被调用。
     * @param terminated_cb 这个传入的函数对象将在工作线程退出前被调用。
     */
    void start(callback_t started_cb = nullptr, callback_t terminated_cb = nullptr);
    /**
     * @brief stop 停止任务，如果当前任务列表为空则立即返回。
     * 如果当前有任务正在被执行则最多等待forceKillTimeout毫秒，如果任务队列中有尚未开始的任务将被丢弃。
     * @param forceKillTimeout
     */
    void stop(unsigned int forceKillTimeout = (unsigned int)(-1));
    /**
     * @brief invokeAsync 将一个任务添加到工作线程的任务列表中，工作线程将按顺序逐个执行列表中的任务。
     * @param cb 工作任务。
     * @remark 当stop调用时，如果任务列表中有未开始的任务，这些任务将被丢弃。
     */
    void invokeAsync(callback_t cb);
    /**
     * @brief invokeSync 以同步方式执行一个任务，即只有这个任务在工作线程中被执行后本函数才会返回。
     * @param cb 工作任务。
     */
    void invokeSync(callback_t cb);
    /**
     * @brief isCurrentThread 判断调用者所在线程是否是工作线程。
     * @return 如果是返回true,否则返回false.
     * @remark 一般而言，不建议在工作线程的上下文中调用此对象的方法（比如this->stop()），而应该在其他线程上下文中调用。
     */
    bool isCurrentThread();
    /**
     * @brief isRunning 工作线程时候正在运行中。
     * @return 如果是返回true,否则返回false.
     */
    bool isRunning();
protected:
    static void* myThread(void* thread_param);
private:
    void processCallbackList();
    CThreadBase m_thread;
    bool m_bTerminte;
    std::deque<callback_t> m_callback_list;
    std::recursive_mutex m_tasks_list_mutex;
    callback_t m_started_cb;
    callback_t m_terminated_cb;
    qcutil::neosmart_event_t m_hEvent;
};
}
